package com.yida.wy.vote.outside.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.yida.common.core.constant.CacheConstants;
import com.yida.common.core.constant.HttpStatus;
import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.domain.R;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.CheckRemoteServiceResultUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.common.core.web.controller.BaseController;
import com.yida.common.core.web.domain.AjaxResult;
import com.yida.common.core.web.page.TableDataInfo;
import com.yida.common.log.annotation.Log;
import com.yida.common.log.enums.BusinessType;
import com.yida.common.redis.service.RedisService;
import com.yida.common.security.utils.SecurityUtils;
import com.yida.gwj.api.domain.request.GwjExpendOutSideAllocatedAmountHouseRequest;
import com.yida.gwj.api.service.RemoteGwjConfigService;
import com.yida.gwj.api.service.RemoteGwjExpendService;
import com.yida.system.api.RemoteSmsService;
import com.yida.system.api.domain.SysSms;
import com.yida.wy.common.domain.request.WyOwnerLoginRequest;
import com.yida.wy.common.valid.Save;
import com.yida.wy.vote.outside.domain.dto.*;
import com.yida.wy.vote.outside.domain.request.WyVoteOwnerProjectQueryRequest;
import com.yida.wy.vote.outside.domain.request.WyVoteResultRequest;
import com.yida.wy.vote.outside.service.IWyVoteOwnerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author lqq
 * @date 2023-03-10
 */
@Api(tags = "投票业主信息")
@RestController
@RequestMapping("/owner")
public class WyVoteOwnerController extends BaseController {
    //投票验证码RedisKey
    private final String VOTE_SMS_KEY = "gwj_vote";

    @Resource
    private IWyVoteOwnerService voteOwnerService;

    @Resource
    private RemoteSmsService remoteSmsService;

    @Resource
    private RedisService redisService;

    @Resource
    private HttpServletRequest httpServletRequest;

    @Resource
    private RemoteGwjExpendService remoteGwjExpendService;

    @Resource
    private RemoteGwjConfigService remoteGwjConfigService;

    @ApiOperation(value = "登录", response = WyVoteOwnerLoginDto.class)
    @PostMapping("/login")
    public AjaxResult login(@Validated(Save.class) @RequestBody WyOwnerLoginRequest request) {
        //验证业主信息
        voteOwnerService.checkOwnerInfo(request);
        //验证短信
        String smsCode = redisService.getCacheObject(getSmsCacheKey(request.getOwnerPhone()));
        if (StringUtils.isBlank(smsCode)) {
            throw new ServiceException("验证码不存在，请重新获取");
        }
        if (!request.getSmsCode().equals(smsCode)) {
            throw new ServiceException("验证码错误");
        }
        //生成自定义token存入redis
        String token = IdUtil.getSnowflakeNextIdStr();
        WyVoteOwnerLoginDto gwjVoteOwnerLoginDto = new WyVoteOwnerLoginDto();
        gwjVoteOwnerLoginDto.setOwnerName(request.getOwnerName());
        gwjVoteOwnerLoginDto.setOwnerPhone(request.getOwnerPhone());
//        gwjVoteOwnerLoginDto.setCardNum(request.getCardNum());
        redisService.setCacheObject(getTokenKey(token), gwjVoteOwnerLoginDto, CacheConstants.EXPIRATION, TimeUnit.MINUTES);
        //返回前端
        Map<String, Object> rspMap = new HashMap<String, Object>();
        rspMap.put("access_token", token);
        rspMap.put("expires_in", CacheConstants.EXPIRATION);
        return AjaxResult.success(rspMap);
    }

    @ApiOperation(value = "获取用户信息")
    @PostMapping("/getInfo")
    public AjaxResult getInfo() {
        checkLogin(httpServletRequest);
        WyVoteOwnerLoginDto gwjVoteOwnerLoginDto = redisService.getCacheObject(getTokenKey(SecurityUtils.getToken(httpServletRequest)));
        WyOwnerLoginRequest request = BeanUtil.copyProperties(gwjVoteOwnerLoginDto, WyOwnerLoginRequest.class);
        List<WyVoteResultDTO> results = voteOwnerService.checkOwnerInfo(request);
//        gwjVoteOwnerLoginDto.setCardNum("");
        gwjVoteOwnerLoginDto.setResultIds(voteOwnerService.getOwnerResultIds(results, request.getOwnerPhone()));
        return AjaxResult.success(gwjVoteOwnerLoginDto);
    }

    /**
     * 需限流
     *
     * @return
     */
    @ApiOperation(value = "获取业主投票地址", response = WyVoteOwnerLoginDto.class)
    @GetMapping("/getVoteUrl")
    public AjaxResult getVoteUrl() {
        R<String> urlR = remoteGwjConfigService.innerGetConfigKey("voting:login:url", SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(urlR)) {
            return AjaxResult.error(urlR.getMsg());
        }
        return AjaxResult.success("查询成功", urlR.getData());
    }

    @ApiOperation(value = "发送短信")
    @PostMapping("/sendSms")
    public AjaxResult sendSms(@Validated @RequestBody WyOwnerLoginRequest request) {
        //验证业主信息
        voteOwnerService.checkOwnerInfo(request);
        //发送短信
        R<SysSms> r = remoteSmsService.sendSmsByPhonenumber(new SysSms() {{
            setSmsType(1);
            setPhonenumber(request.getOwnerPhone());
            setSms("短信");
            setSmsSource(VOTE_SMS_KEY);
        }}, SecurityConstants.INNER);
        AjaxResult result = toAjax(!CheckRemoteServiceResultUtils.isCodeFail(r));
        if (StringUtils.isNotNull(r.getData())){
            result.put(AjaxResult.MSG_TAG,r.getData().getSms());
        }else {
            result.put(AjaxResult.MSG_TAG, r.getMsg());
        }
        return result;
    }

    @ApiOperation(value = "获取公维金投票项目详细信息", response = WyVoteProjectDetailDTO.class)
    @GetMapping(value = "/gwjVote/{voteId}/{resultId}")
    public AjaxResult getGwjVoteInfo(@PathVariable("voteId") Long voteId, @PathVariable("resultId") Long resultId) {
        checkLogin(httpServletRequest);
        return AjaxResult.success(voteOwnerService.voteGwjDetail(voteId, resultId));
    }

    @ApiOperation(value = "获取投票项目详细信息", response = WyVoteProjectDetailDTO.class)
    @GetMapping(value = "/{voteId}/{resultId}")
    public AjaxResult getInfo(@PathVariable("voteId") Long voteId, @PathVariable("resultId") Long resultId) {
        checkLogin(httpServletRequest);
        return AjaxResult.success(voteOwnerService.voteDetail(voteId, resultId));
    }

    @ApiOperation(value = "获取投票票根", response = WyVoteOwnerTicketStubDetailDTO.class)
    @GetMapping(value = "/ticketStub/{voteId}/{resultId}")
    public AjaxResult ticketStub(@PathVariable("voteId") Long voteId, @PathVariable("resultId") Long resultId) {
        checkLogin(httpServletRequest);
        return AjaxResult.success(voteOwnerService.ticketStub(voteId, resultId));
    }

    @ApiOperation(value = "查询业主可投票项目列表", response = WyVoteOwnerProjectListDTO.class)
    @PostMapping("/projectList")
    public TableDataInfo ownerProject(@RequestBody WyVoteOwnerProjectQueryRequest request) {
        startPage();
        checkLogin(httpServletRequest);
        return getDataTable(StringUtils.isEmpty(request.getResultIds()) ? new ArrayList<WyVoteOwnerProjectListDTO>() : voteOwnerService.selectVoteOwnerProjectList(request));
    }

    @ApiOperation("业主投票")
    @Log(title = "公维金外网投票-业主投票结果", businessType = BusinessType.INSERT_UPDATE, systemName = "vote")
    @PostMapping
    public AjaxResult add(@Validated @RequestBody WyVoteResultRequest request) {
        checkLogin(httpServletRequest);
        return toAjax(voteOwnerService.addOrUpdateVoteResult(request));
    }

    @ApiOperation("退出登录")
    @DeleteMapping("/logout")
    public AjaxResult logout() {
        redisService.deleteObject(getTokenKey(SecurityUtils.getToken(httpServletRequest)));
        return AjaxResult.success();
    }

    @ApiOperation("报价单")
    @GetMapping("/expendImg")
    public AjaxResult expendImg(@RequestParam("bizNum") Long bizNum, @RequestParam("areaId") Long areaId) {
        R<JSONArray> r = remoteGwjExpendService.expendImg(bizNum, areaId, SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(r)) {
            return AjaxResult.error(r.getMsg());
        }
        return AjaxResult.success(r.getData());
    }

    @ApiOperation("分摊范围及金额")
    @PostMapping("/expendBusinessHouse")
    public AjaxResult expendBusinessHouse(@RequestBody GwjExpendOutSideAllocatedAmountHouseRequest request) {
        R<JSONObject> r = remoteGwjExpendService.expendBusinessHouse(request, SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(r)) {
            return AjaxResult.error(r.getMsg());
        }
        return AjaxResult.success(r.getData());
    }

    @ApiOperation("查询未选中房屋")
    @PostMapping("/expendBusinessHouse/unselected")
    public AjaxResult expendBusinessHouseUnselected(@RequestBody GwjExpendOutSideAllocatedAmountHouseRequest request) {
        R<JSONObject> r = remoteGwjExpendService.expendBusinessHouseUnselected(request, SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(r)) {
            return AjaxResult.error(r.getMsg());
        }
        return AjaxResult.success(r.getData());
    }

    @ApiOperation("维修和更新、改造方案")
    @GetMapping("/expendFile")
    public AjaxResult expendFile(@RequestParam("bizNum") Long bizNum, @RequestParam("areaId") Long areaId) {
        R<JSONObject> r = remoteGwjExpendService.expendFile(bizNum, areaId, SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(r)) {
            return AjaxResult.error(r.getMsg());
        }
        return AjaxResult.success(r.getData());
    }

    @ApiOperation("查询业务楼栋信息")
    @GetMapping("/expendBusinessBuilds")
    public AjaxResult expendBusinessBuilds(@RequestParam("bizNum") Long bizNum, @RequestParam("areaId") Long areaId) {
        R<JSONArray> r = remoteGwjExpendService.expendBusinessBuilds(bizNum, areaId, SecurityConstants.INNER);
        if (CheckRemoteServiceResultUtils.isCodeFail(r)) {
            return AjaxResult.error(r.getMsg());
        }
        return AjaxResult.success(r.getData());
    }

    /**
     * 检查登录
     *
     * @param request 请求
     */
    private void checkLogin(HttpServletRequest request) {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isEmpty(token)) {
            throw new ServiceException("token不能为空", HttpStatus.UNAUTHORIZED);
        }
        boolean isLogin = redisService.hasKey(getTokenKey(token));
        if (!isLogin) {
            throw new ServiceException("登录状态已过期", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取缓存key
     */
    private String getTokenKey(String token) {
        //业主登录RedisKey
        return "owner_login_tokens:" + token;
    }

    public String getSmsCacheKey(String ownerPhone) {
        return CacheConstants.SMS_CODE_EXPIRATION_KEY + VOTE_SMS_KEY + ":" + ownerPhone;
    }
}
